from google.appengine.api import urlfetch
import logging, urllib
from django.utils import simplejson
import dlz_config as dc
#from ft_table import FtTable
from upload import *
from google.appengine.api import mail
from google.appengine.api import users



class IformTable():
    def __init__(self, username, password, page_id, table_name):
        self.page_id = page_id
        self.table_name = table_name
        self.username = username
        self.password = password
        self.data = None
    def query(self, since_id):
        logging.info('query iformtable, since_id=%s' % since_id)
        return download_table(self.username, self.password, self.page_id, self.table_name, record_id=None, since_id = since_id )
    
    def all(self):
        return download_table(self.username, self.password, self.page_id, self.table_name, record_id=None )
        
    def get(self, ID):
        return download_table(self.username, self.password, self.page_id, self.table_name, record_id=ID )
    
def process_iform_json(data):
    '''
    process the json returned from iformbuilder server
    extract the lat, lon
    '''
    results = []
    for item in data:
        result = {}
        record = item.get('record')
        location = item.get('location')
        for k, v in record.items():
            result[k] = v
        if location:
            result['lat'] = location.get('lat')
            result['lon'] = location.get('lon')
        results.append(result)
    return results
    
def download_table(username, password,page_id, table_name, record_id=None, since_id=None, qtype=None ):
    '''download a table and return a json'''
    if username is None:
        username = dc.get('IFORM_USER')
    if password is None:
        password = dc.get('IFORM_PASSWORD')
    
    form_fields = {
      "USERNAME": username,
      "PASSWORD": password,
      'PAGE_ID': page_id,
      'TABLE_NAME': table_name,
      'TYPE': 'TOP'
    }
    if since_id:
        form_fields['SINCE_ID'] = since_id
    if record_id:
        form_fields['ID'] = record_id
    if qtype:
        form_fields['TYPE'] = qtype
        
    url = dc.get('IFORM_URL')
    logging.info('Downloading data from iFormBuilder: %s, %s' % (page_id, table_name))
    form_data = urllib.urlencode(form_fields)
    result = urlfetch.fetch(url=url,
                    payload=form_data,
                    method=urlfetch.POST)
    data = simplejson.loads(result.content)
    logging.info('data downloaded: %s' % str(data)[:100])
    return data


def update_project_info(gae_form_table, gae_test_table):
    '''
    pull the project information from the dlz_project_list table and update the gae tables.
    '''
    # get a list of all the project
    q = model.dlz_project_list.all()
    project_list = []
    for r in q:
        project = {}
        for fld in 'project_name project_number client_name'.split():
            project[fld] = getattr(r, fld)
        project_list.append(project)
    
    def get_project(project_key):
        '''if the project_key starts with the project number, then it returns the project
        setup this way so that the project_num doesn't need to be fixed length.'''
        for p in project_list:
            project_number = p['project_number']
            if project_key.startswith(project_number):
                return p
    
    #update the compaction_form
    q = gae_form_table.all().filter('project_number = ', None)
    batch = []
    for t in q:
        p = get_project(t.project_key)
        if p:
            for fld in 'project_name project_number client_name'.split():
                setattr(t, fld, p[fld])
            logging.info('Updating project info for compation_form for :%s' % t.project_key)
        else:
            msg = 'Missing Project Information for : %s' % (t.project_key)
            logging.warning(msg)
            email_notify('ymeng@dlz.com', 'Missing Project', msg)
        batch.append(t)
        logging.info('updates saved.')
    db.put(batch)
    #update the compaction_test
    q = gae_test_table.all().filter('project_number = ', None)
    batch = []
    for t in q:
        form_id = t.PARENT_RECORD_ID
        q2 = gae_form_table.all().filter('ID = ', form_id)
        for f in q2.fetch(1):
            if f.project_number:
                logging.info('Updating project info for compation_test(%s) for :%s' % (t.ID, f.project_key))
                for fld in 'project_name project_number client_name nuclear_no ds1 ds2 tested_by ms model form_date'.split():
                    v = getattr(f, fld)
                    setattr(t, fld, v)
            else:
                logging.warning('Missing project info for compation_test(%s) for :%s' % (t.ID, f.project_key))
        batch.append(t)
        
    db.put(batch)
    logging.info('updates saved.')
    
def update_compaction_project_info():
    update_project_info(model.compaction_form, model.compaction_test)


def update_asphalt_project_info():
    update_project_info(model.asphalt_form, model.asphalt_test)




def sync_iform_table(dlz_table_name, since_id, processing_fn, insert_fn):
    '''
    sync the data from iform to gae_table
    '''
    q = model.dlz_connection.all().filter('dlz_table_name = ', dlz_table_name)
    ts = {}
    for r in q:
        ts['iform_page_id'] = r.iform_page_id
        ts['iform_table_name'] = r.iform_table_name
        ts['gae_table_name'] = r.gae_table_name
        
    iform_table = IformTable(None, None, ts['iform_page_id'], ts['iform_table_name'])
    try:
        gae_table = getattr(model, ts['gae_table_name'])
    except:
        logging.fatal('%s definition in the dlz_connection is incorrect' % ts['gae_table_name'])
        raise AttributeError
    #if since id is not provided, find the newest ID
    if since_id is not None:
        #use the supplied value, it should be an integer
        since_id = int(since_id)
        
    else:
        #find the newest ID
        q = gae_table.all().order('-ID')
        result = q.fetch(1)
        if result:
            #get a return value
            since_id = result[0].ID
        else:
            #it is an empty table, use 0
            since_id = 0
            
    data = iform_table.query(since_id)
    
    if data:
        #there are updated records
        #turn json into a records format
        data = processing_fn(data)
        #do the insert
        insert_fn(data)
        


def sync_compaction_form(since_id=None):
    sync_iform_table('DLZ_COMPACTION_FORM', None, process_iform_json, insert_compaction_form)

        
    
def sync_compaction_test(since_id=None):
    sync_iform_table('DLZ_COMPACTION_TEST', None, process_iform_json, insert_compaction_test)

def sync_asphalt_form(since_id=None):
    sync_iform_table('DLZ_ASPHALT_FORM', None, process_iform_json, insert_asphalt_form)

def sync_asphalt_test(since_id=None):
    sync_iform_table('DLZ_ASPHALT_TEST', None, process_iform_json, insert_asphalt_test)

def email_notify(email_address, subject, message):
    '''
    send an email
    '''
    mail.send_mail(sender=users.get_current_user().email(),
              to=email_address,
              subject=subject,
              body=message)
    logging.info('Email is sent to %s : %s' % (email_address, message))